bitkeeper revision 1.137 (3e745d6egPhbuKyLs12XPZOtKEunKA)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Sun, 16 Mar 2003 11:18:06 +0000 (11:18 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Sun, 16 Mar 2003 11:18:06 +0000 (11:18 +0000)
schedule.c, ac_timer.c, time.c, apic.c:
  Some timer fixes.

xen/arch/i386/apic.c
xen/arch/i386/time.c
xen/common/ac_timer.c
xen/common/schedule.c

index 2621bd11093c3cf802f41370fe569264618ac6a9..e8e25e7f17d9ec8035013268eaeedc3f8579dabc 100644 (file)
  */
 
 /*
- *     Local APIC handling, local APIC timers
+ *  Local APIC handling, local APIC timers
  *
- *     (c) 1999, 2000 Ingo Molnar <mingo@redhat.com>
+ *  (c) 1999, 2000 Ingo Molnar <mingo@redhat.com>
  *
- *     Fixes
- *     Maciej W. Rozycki       :       Bits for genuine 82489DX APICs;
- *                                     thanks to Eric Gilmore
- *                                     and Rolf G. Tews
- *                                     for testing these extensively.
+ *  Fixes
+ *  Maciej W. Rozycki   :   Bits for genuine 82489DX APICs;
+ *                  thanks to Eric Gilmore
+ *                  and Rolf G. Tews
+ *                  for testing these extensively.
  */
 
 
@@ -329,13 +329,13 @@ void __init setup_local_APIC (void)
         value = APIC_DM_NMI;
     else
         value = APIC_DM_NMI | APIC_LVT_MASKED;
-    if (!APIC_INTEGRATED(ver))         /* 82489DX */
+    if (!APIC_INTEGRATED(ver))      /* 82489DX */
         value |= APIC_LVT_LEVEL_TRIGGER;
     apic_write_around(APIC_LVT1, value);
 
-    if (APIC_INTEGRATED(ver)) {                /* !82489DX */
+    if (APIC_INTEGRATED(ver)) {     /* !82489DX */
         maxlvt = get_maxlvt();
-        if (maxlvt > 3)                /* Due to the Pentium erratum 3AP. */
+        if (maxlvt > 3)     /* Due to the Pentium erratum 3AP. */
             apic_write(APIC_ESR, 0);
         value = apic_read(APIC_ESR);
         printk("ESR value before enabling vector: %08lx\n", value);
@@ -653,25 +653,28 @@ void __init setup_APIC_clocks (void)
  */
 int reprogram_ac_timer(s_time_t timeout)
 {
-    int                cpu = smp_processor_id();
-    s_time_t   now;
-    s_time_t   expire;
-    u64                        apic_tmict;
-
-    if (timeout  == 0) {
-        /* XXX RN: not sure if this disables it or cause interruptto 
-         * go off imediately */
-        apic_tmict = 0;
+    int         cpu = smp_processor_id();
+    s_time_t    now;
+    s_time_t    expire;
+    u64         apic_tmict;
+
+    /*
+     * We use this value because we don't trust zero (we think it may just
+     * cause an immediate interrupt). At least this is guaranteed to hold it
+     * off for ages (esp. since the clock ticks on bus clock, not cpu clock!).
+     */
+    if (timeout == 0) {
+        apic_tmict = 0xffffffff;
         goto reprogram;
     }
 
     now = NOW();
-    expire = timeout - now;    /* value from now */
+    expire = timeout - now; /* value from now */
 
     if (expire <= 0) {
         printk("APICT[%02d] Timeout in the past 0x%08X%08X > 0x%08X%08X\n", 
                cpu, (u32)(now>>32), (u32)now, (u32)(timeout>>32),(u32)timeout);
-        return 0;              /* timeout value in the past */
+        return 0;       /* timeout value in the past */
     }
 
     /* conversion to bus units */
@@ -687,7 +690,7 @@ int reprogram_ac_timer(s_time_t timeout)
     }
 
  reprogram:
-    /* programm timer */
+    /* Program the timer. */
     apic_write(APIC_TMICT, (unsigned long)apic_tmict);
 
     TRC(printk("APICT[%02d] reprog(): expire=%lld %u\n",
@@ -755,9 +758,9 @@ void smp_apic_timer_interrupt(struct pt_regs * regs)
      */
     ack_APIC_irq();
 
-       /* call the local handler */
+    /* call the local handler */
     irq_enter(cpu, 0);
-       perfc_incrc(apic_timer);
+    perfc_incrc(apic_timer);
     smp_local_timer_interrupt(regs);
     irq_exit(cpu, 0);
 
index 773c4cfeb3160eceb9e8a2afc22011d828bdb718..d03767ef2b3a73ea62571489dec6ace81990c953 100644 (file)
@@ -240,15 +240,12 @@ static u32        st_scale_i;
 u32                    stime_pcc;       /* cycle counter value at last timer irq */
 s_time_t       stime_now;   /* time in ns at last timer IRQ */
 
-s_time_t get_s_time(void)
+static inline s_time_t __get_s_time(void)
 {
-    unsigned long flags;
     u32         delta_tsc, low, pcc;
     u64      delta;
     s_time_t now;
 
-    spin_lock_irqsave(&stime_lock, flags);
-
     pcc = stime_pcc;           
     now = stime_now;
 
@@ -259,9 +256,17 @@ s_time_t get_s_time(void)
     delta >>= 32;
     delta += ((u64)delta_tsc * st_scale_i);
 
-    spin_unlock_irqrestore(&stime_lock, flags);
+    return now + delta;
+}
 
-    return now + delta; 
+s_time_t get_s_time(void)
+{
+    s_time_t now;
+    unsigned long flags;
+    spin_lock_irqsave(&stime_lock, flags);
+    now = __get_s_time();
+    spin_unlock_irqrestore(&stime_lock, flags);
+    return now; 
 }
 
 
@@ -326,17 +331,13 @@ static struct ac_timer update_timer;
 static void update_time(unsigned long foo)
 {
     unsigned long  flags;
-    u32                       new_pcc;
     s_time_t       new_st;
     unsigned long  usec;
 
-    new_st = NOW();
-    rdtscl(new_pcc);
-
     /* Update system time. */
     spin_lock_irqsave(&stime_lock, flags);
-    stime_now = new_st;
-    stime_pcc=new_pcc;
+    stime_now = new_st = __get_s_time();
+    rdtscl(stime_pcc);
     /* Don't reeenable IRQs until we release wctime_lock. */
     spin_unlock(&stime_lock);
 
index 73ac893e083842d3ae938e7bf156932b76cf36db..4505712bf31ac7b66badc02acb821a92145f9a49 100644 (file)
@@ -82,7 +82,9 @@ int add_ac_timer(struct ac_timer *timer)
                    (u32)(timer->expires>>32), (u32)timer->expires));
         return 1;
     }
+
     spin_lock_irqsave(&ac_timers[cpu].lock, flags);
+
     /*
      * Add timer to the list. If it gets added to the front we have to
      * reprogramm the timer
@@ -154,8 +156,12 @@ int rem_ac_timer(struct ac_timer *timer)
             /* just removed the head */
             if (list_empty(&ac_timers[cpu].timers)) {
                 reprogram_ac_timer((s_time_t) 0);
+            } else {
+                timer = list_entry(ac_timers[cpu].timers.next,
+                                   struct ac_timer, timer_list);
+                if ( timer->expires > (NOW() + TIMER_SLOP) )
+                    reprogram_ac_timer(timer->expires);
             }
-            /* XXX should actaully reprogramm APIC to new head */
         }
     } else
         res = -1;
@@ -201,13 +207,7 @@ void do_ac_timer(void)
         
     /* Sanity: is the timer list empty? */
     if ( list_empty(&ac_timers[cpu].timers) ) {
-        /*
-         * XXX RN: This shouldn't happen, but does! Two possibilities:
-         * - Race condition between removing and reseting APIC
-         * - setting an APIC timeout value of 0 causes an immediate
-         *   timer interrupt to fire.
-         * None of these should be critical!
-         */
+        /* This does sometimes happen: race condition in resetting timeout? */
         spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
         return;
     }
index 3ef29e3c5cb24dd764e7b159d4159ac75b91364b..9842036c98401ff8e808678b2c47e71d180043b6 100644 (file)
@@ -368,9 +368,9 @@ asmlinkage void schedule(void)
 
  sched_done:
     ASSERT(r_time != 0);
-    ASSERT(r_time > ctx_allow);
+    ASSERT(r_time >= ctx_allow);
 
-#if 0
+#ifndef NDEBUG
     if ( (r_time==0) || (r_time < ctx_allow)) {
         printk("[%02d]: %lx\n", this_cpu, r_time);
         dump_rqueue(&schedule_data[this_cpu].runqueue, "foo");
@@ -389,7 +389,8 @@ asmlinkage void schedule(void)
  timer_redo:
     schedule_data[this_cpu].s_timer.expires  = now + r_time;
     if (add_ac_timer(&schedule_data[this_cpu].s_timer) == 1) {
-        printk("SCHED[%02d]: Shit this shouldn't happen\n", this_cpu);
+        printk("SCHED[%02d]: Shit this shouldn't happen %08x\n", 
+               this_cpu, r_time);
         now = NOW();
         goto timer_redo;
     }